package tt.dz.egobus.servicemanager.base.dao;

import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import tt.dz.egobus.base.dao.AbstractBaseDao;
import tt.dz.egobus.base.entity.BaseEntity;
import tt.dz.egobus.bean.CriteriaRestrictionsBuilder;
import tt.dz.egobus.servicemanager.bean.PagingationStart;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.*;

import static tt.dz.egobus.servicemanager.bean.CriteriaRestrictionHelper.packageOrders;
import static tt.dz.egobus.servicemanager.bean.CriteriaRestrictionHelper.packageParamCriteria;

/**
 * @author Anson
 * @date 17-3-14
 * @name 扩展dao实现类
 * @since 1.0.1
 */
public abstract class AbstractExtendDao<E extends BaseEntity, PK extends Serializable> extends AbstractBaseDao<E, PK>
        implements ExtendDao<E, PK> {

    /**
     * 查询数据库当前的时间
     */
    private static final String SELECT_DB_CURRENT_TIME = "select CURRENT_TIMESTAMP ";


    @Override
    public List<E> list(Map<String, Object> params) {
        return this.list(params, null);
    }

    @Override
    public List<E> list(Map<String, Object> params, List<String> orders) {
        Criteria criteria = this.getCriteria();
        CriteriaRestrictionsBuilder criteriaRestrictionsBuilder =
                packageParamCriteria(criteria, params);
        packageOrders(criteriaRestrictionsBuilder, orders);
        criteria.setProjection(null);
        criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        criteria = criteriaRestrictionsBuilder.builder();
        List<E> result = (List<E>) criteria.list();
        return result == null ? new ArrayList<E>(0) : result;
    }

    @Override
    public int count(Map<String, Object> params) {
        Criteria criteria = this.getCriteria();
        packageParamCriteria(criteria, params);
        criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        Object obj = criteria.setProjection(
                Projections.rowCount()).uniqueResult();
        int rowCount = obj == null ? 0 : ((Long) obj).intValue();
        return rowCount;
    }

    @Override
    public List<E> queryByIds(PK[] ids) {
        Criteria criteria = this.getCriteria();
        criteria.add(Restrictions.in("id", ids));
        criteria.setProjection(null);
        criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        return criteria.list();
    }

    @Override
    public Date getDbDate() {
        List<Timestamp> timestamps = this.getSQLQuery(SELECT_DB_CURRENT_TIME).list();
        if (timestamps == null) {
            return new Date();
        }
        return timestamps.get(0);
    }

    @Override
    public PagingationStart<E> paginationStart(Map<String, Object> params, int start, int maxResult, int maxResult1) {
        return this.paginationStart(params, start, maxResult, null);
    }

    @Override
    public PagingationStart<E> paginationStart(Map<String, Object> params, int start, int maxResult,
                                               List<String> orderList) {
        Criteria criteria = this.getCriteria();

        CriteriaRestrictionsBuilder criteriaRestBuilder = new CriteriaRestrictionsBuilder(criteria);
        if (null != params && !params.isEmpty()) {
            Map.Entry<String, Object> entry = null;
            for (Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
                 iterator.hasNext(); ) {
                entry = iterator.next();
                criteriaRestBuilder.contact(entry.getKey(), entry.getValue());
            }
            criteria = criteriaRestBuilder.builder();
        }
        // 获取根据条件分页查询的总行数
        Object obj = criteria.setProjection(
                Projections.rowCount()).uniqueResult();
        int rowCount = obj == null ? 0 : ((Long) obj).intValue();
        //添加排序
        if (null != orderList && !orderList.isEmpty()) {
            for (String order : orderList) {
                criteriaRestBuilder.order(order);
            }
        }
        criteria = criteriaRestBuilder.builder();

        PagingationStart<E> pagination = new PagingationStart<E>();
        pagination.setOffset(start);
        pagination.setPageSize(maxResult);
        pagination.setAllRow(rowCount);
        criteria.setProjection(null);
        criteria.setFirstResult(pagination.countOffset());
        criteria.setMaxResults(maxResult);
        criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
        List<E> result = rowCount == 0 ? new ArrayList<E>(0) : (List<E>) criteria.list();
        pagination.setList(result);
        return pagination;
    }
}
